﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Web;

namespace XMK.Framework.DataAccess
{
    /// <summary>
    /// sql server的数据库缓存
    /// </summary>
    public class SqlDbDependency<T> : DbDependency<T> where T : new()
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connString">数据库连接字符串</param>
        /// <param name="sqlText">数据库查询字符串</param>
        /// <param name="fun">对象填充委托</param>
        public SqlDbDependency(string connString, string sqlText, DataRowFullInfoFun<T> fun)
        {
            this.SqlText = sqlText;
            this.CacheKey = "SqlDbDependency_" + this.SqlText;
            this.ConnString = connString;
            this.Fun = fun;
        }
        /// <summary>
        /// 使用缓存机制获取数据
        /// </summary>
        /// <returns>需要的列表</returns>
        public override List<T> GetCacheData()
        {
            List<T> list = HttpRuntime.Cache[this.CacheKey] as List<T>;
            if (list == null)
            {
                //DataTable dt = GetCacheData();
                list = GetData();
                HttpRuntime.Cache[this.CacheKey] = list;
            }
            return list;
        }
        #region 数据库依赖的私有方法
        /// <summary>
        /// 获取缓存列表
        /// </summary>
        /// <returns>缓存对象</returns>
        private List<T> GetData()
        {
            using (SqlConnection conn = new SqlConnection(ConnString))
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand(SqlText, conn);
                //清除    
                cmd.Notification = null;
                //设置通知    
                SqlDependency dep = new SqlDependency(cmd);
                //通知事件    
                dep.OnChange += new OnChangeEventHandler(DataOnChange);
                
                DataTable dt = new DataTable();
                using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) //查询数据
                {
                    try
                    {
                        if (conn.State != ConnectionState.Open)
                        {
                            conn.Open();
                        }
                        adapter.Fill(dt);
                        return DbManager.DataTableFullInfos<T>(dt, this.Fun);
                        //return dt;
                    }
                    finally
                    {
                        adapter.Dispose();
                        cmd.Dispose();
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 通知事件，清除缓存
        /// </summary>
        /// <param name="sender">事件激发者</param>
        /// <param name="e">事件参数</param>
        private void DataOnChange(Object sender, SqlNotificationEventArgs e)
        {
            SqlDependency dep = (SqlDependency)sender;
            dep.OnChange -= new OnChangeEventHandler(DataOnChange);
            //更新缓存
            HttpRuntime.Cache.Remove(this.CacheKey);
            //通知之后,当前Dependency失效,重新获取数据并设置通知    
            HttpRuntime.Cache[this.CacheKey] = GetData();
        }
        #endregion
    }
}
